package web.stu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import web.stu.common.ErrorCode;
import web.stu.exception.BusinessException;
import web.stu.mapper.ClassMapper;
import web.stu.mapper.TeacherCourseMapper;
import web.stu.model.dto.clazz.ClassDTO;
import web.stu.model.entity.Class;
import web.stu.model.entity.User;
import web.stu.model.enums.UserRoleEnum;
import web.stu.model.vo.ClassVO;
import web.stu.model.vo.UserVO;
import web.stu.service.ClassService;
import web.stu.service.UserService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author administer
 * @description 针对表【class(班级表)】的数据库操作Service实现
 * @createDate 2025-05-13 19:55:10
 */
@Slf4j
@Service
public class ClassServiceImpl extends ServiceImpl<ClassMapper, Class>
        implements ClassService {

    @Resource
    private ClassMapper classMapper;

    @Resource
    private UserService userService;

    @Resource
    private TeacherCourseMapper teacherCourseMapper;

    @Override
    public List<ClassVO> listAllClasses() {
        List<Class> list = this.list();
        List<ClassVO> classVOList = list.stream().map(clazz -> {
            Integer stuCount = classMapper.getStuCountByClassId(clazz.getId());
            ClassVO classVO = BeanUtil.copyProperties(clazz, ClassVO.class);
            classVO.setStuCount(stuCount);
            return classVO;
        }).collect(Collectors.toList());

        return classVOList;
    }

    @Override
    public Page<ClassVO> pageClasses(ClassDTO classDTO) {
        // 非空判断
        if (classDTO == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        Page<Class> page = page(this.page(new Page<>(classDTO.getCurrent(), classDTO.getPageSize())), getQueryWrapper(classDTO));
        List<ClassVO> classVOList = page.getRecords().stream().map(clazz -> {
            Integer stuCount = classMapper.getStuCountByClassId(clazz.getId());
            ClassVO classVO = BeanUtil.copyProperties(clazz, ClassVO.class);
            classVO.setStuCount(stuCount);
            return classVO;
        }).collect(Collectors.toList());
        Page<ClassVO> classVOPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        classVOPage.setRecords(classVOList);
        return classVOPage;
    }

    @Override
    public void addClass(ClassDTO classDTO, HttpServletRequest request) {
        // 查询权限 不是管理无权操作
        User loginUser = userService.getLoginUser(request);
        if (!userService.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "不为管理员，不能删除课程");
        }
        // 检查班级名称是否已存在
        LambdaQueryWrapper<Class> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Class::getClassName, classDTO.getClassName());
        if (this.count(wrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "班级名称已存在");
        }

        Class clazz = new Class();
        clazz.setClassName(classDTO.getClassName());
        clazz.setGrade(classDTO.getGrade());
        clazz.setMajor(classDTO.getMajor());
        clazz.setCreateTime(new Date());
        clazz.setUpdateTime(new Date());

        if (!this.save(clazz)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加班级失败");
        }
        log.info("添加班级成功: {}", classDTO.getClassName());
    }

    @Override
    public void updateClass(ClassDTO classDTO, HttpServletRequest request) {
        // 查询权限 不是管理无权操作
        User loginUser = userService.getLoginUser(request);
        if (!userService.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "不为管理员，不能删除课程");
        }
        // 检查班级是否存在
        Class existingClass = this.getById(classDTO.getId());
        if (existingClass == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "班级不存在");
        }

        // 检查班级名称是否与其他班级冲突
        LambdaQueryWrapper<Class> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Class::getClassName, classDTO.getClassName())
                .ne(Class::getId, classDTO.getId());
        if (this.count(wrapper) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "班级名称已存在");
        }

        Class clazz = new Class();
        clazz.setId(classDTO.getId());
        clazz.setClassName(classDTO.getClassName());
        clazz.setGrade(classDTO.getGrade());
        clazz.setMajor(classDTO.getMajor());
        clazz.setUpdateTime(new Date());

        if (!this.updateById(clazz)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新班级失败");
        }
        log.info("更新班级成功, ID: {}", classDTO.getId());
    }

    @Override
    public void deleteClassById(Integer id, HttpServletRequest request) {
        // 查询权限 不是管理无权操作
        User loginUser = userService.getLoginUser(request);
        if (!userService.isCompareRole(loginUser, UserRoleEnum.ADMIN.getKey())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "不为管理员，不能删除课程");
        }
        // 检查班级是否存在
        Class existingClass = this.getById(id);
        // 检查班级是否存在
        if (existingClass == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "班级不存在");
        }

        // 判断是否存在其他表中 student_class teacher_class
        if (classMapper.countClassStudentClass(id) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该班级下还有学生记录，无法删除");
        }
        if (teacherCourseMapper.countClassTeacherCourse(id) > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "该班级下还有教师授课记录，无法删除");
        }

        if (!this.removeById(id)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除班级失败");
        }
    }

    @Override
    public ClassVO getClassById(Integer id) {
        Class clazz = this.getById(id);
        if (clazz == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "班级不存在");
        }
        Integer stuCount = classMapper.getStuCountByClassId(clazz.getId());
        ClassVO classVO = BeanUtil.copyProperties(clazz, ClassVO.class);
        classVO.setStuCount(stuCount);
        return classVO;
    }

    private QueryWrapper<Class> getQueryWrapper(ClassDTO classDTO) {
        QueryWrapper<Class> wrapper = new QueryWrapper<>();
        // 非空判断
        if (classDTO == null) {
            return wrapper;
        }
        //  提取变量
        Integer id = classDTO.getId();
        String className = classDTO.getClassName();
        String grade = classDTO.getGrade();
        String major = classDTO.getMajor();

        // 进行匹配
        wrapper.eq(id != null, "id", id);
        wrapper.like(StrUtil.isNotBlank(className), "class_name", className);
        wrapper.like(StrUtil.isNotBlank(grade), "grade", grade);
        wrapper.like(StrUtil.isNotBlank(major), "major", major);


        return wrapper;


    }

    @Override
    public Integer getStuCountByClassId(Integer id) {
        // 非空判断
        if (id == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        // 查询班级是否存在
        Class aClass = getById(id);
        if (aClass == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "目标班级不存在");
        }
        // 统计人数
        Integer count = classMapper.getStuCountByClassId(id);
        if (count < 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "统计班级人数失败");
        }
        return count;
    }

    @Override
    public List<ClassVO> getClassByTeacherId(Integer teacherId, HttpServletRequest request) {
        // 非空判断
        if (teacherId == null) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        //
        List<Class> classList = classMapper.getClassByTeacherId(teacherId);
        List<ClassVO> classVOList = classList.stream().map(clazz -> BeanUtil.copyProperties(clazz, ClassVO.class)).collect(Collectors.toList());

        return classVOList;
    }

    @Override
    public int addStudentsByClass(List<Integer> studentIds, Integer classId) {
        // 非空判断
        if (studentIds == null || CollUtil.isEmpty(studentIds)) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR);
        }
        Class byId = getById(classId);
        if (byId == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "课程不存在");
        }
        // 查询学生是否存在
        List<User> studentList = userService.list(new QueryWrapper<User>().select("id").eq("role", UserRoleEnum.STUDENT.getKey()));
        studentIds.forEach(id -> {
            if (studentList.stream().noneMatch(u -> Objects.equals(u.getId(), id))) {
                throw new BusinessException(ErrorCode.PRIMARY_ERROR, "添加学生不存在");
            }
        });
        // 判断是否存在
        Integer count = classMapper.getCountByStudentClassId(studentIds, null);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PRIMARY_ERROR, "添加学生中已存在记录");
        }
        // 添加
        int res = classMapper.addStudentsByClass(studentIds, classId);
        if (res <= 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加失败");
        }
        return res;
    }

    @Override
    public List<UserVO> getStudentListDontSelectClass(HttpServletRequest request) {

        List<User> userList = classMapper.getStudentListDontSelectClass();

        return userList.stream().map(UserVO::objToVO).collect(Collectors.toList());
    }


}




